#!/usr/bin/env python2
#-*- coding: utf-8 -*-

import os
import re
import sys
import time
import json
import traceback
import threading
import datetime

from Ump import utils
from Ump.common import config
from Ump.common import log

from Ump.objs.db import models
from Ump.objs.session_wrapper import enable_log_and_session
from Ump.objs.manager_base import Manager
from Ump.objs.alert.api import AlertApi

LOG = log.get_log('Ump.objs.monitor.manager')

alert_api = AlertApi()

class MonitorManager(Manager):

    def __init__(self):
        super(MonitorManager, self).__init__()

    def monitor_main_for_bin(self):
        return self.monitor_main()

    def monitor_main(self):
        '''同步所有的集群，如果没有任何错误方式，msgs为空, 否则非空 '''
        cluster = models.Cluster.query.first()
        msgs = []
        error = self.utils.exception_pass(self._check_syslog, cluster)
        return msgs
    
    def _check_syslog(self, cluster):
        for host in cluster.hosts:
            syslogPath = self._get_syslog_path(host.ip)

            wc_syslog_cmd = "wc -l %s|awk '{print $1}'" % (syslogPath)
            res = self.api_sync_call(host.ip, wc_syslog_cmd)

            end_line = res.strip()
            start_line = host.syslog_start_line
            if int(end_line) < int(host.syslog_start_line) - 1:
                messages_back_cmd = "ls -t %s*|sed -n '2p'" % (syslogPath)
                messages_path = self.api_sync_call(host.ip, messages_back_cmd)
                sed_cmd = "sed -n '1, %sp' %s|grep -E '^\S+\s+\S+\s+\S+\s+\S+\s+FusionStor'" %  (end_line, syslogPath)
                if messages_path:
                    rotating_log_cmd = "sed -n '%s, $p' %s |grep -E '^\S+\s+\S+\s+\S+\s+\S+\s+FusionStor'" % (start_line, messages_path.strip())
                    sed_cmd = rotating_log_cmd + ';' + sed_cmd
            else:
                sed_cmd = "sed -n '%s, %sp' %s|grep -E '^\S+\s+\S+\s+\S+\s+\S+\s+FusionStor'; echo ''" % (start_line, end_line, syslogPath)
    
            now = datetime.datetime.now()
            is_pass_time = self.utils.time_greater_than(host.syslog_time, seconds=1200)
            if not is_pass_time :
                syslog_tail = ''
                try:
                    syslog_tail = self.api_sync_call(host.ip, sed_cmd)
                    host.update({'syslog_start_line': int(end_line) + 1 })
                except Exception, e:
                    pass
                self._syslog_analysis(syslog_tail, host)
            else:
                host.update({'syslog_start_line': int(end_line) + 1 ,'syslog_time':now})

    def _syslog_analysis(self, syslog_tail, host):
        syslogs = syslog_tail.split('\n')
        is_send2ui = False
        for log in syslogs:
            if not log:
                continue
        
            level = self.__compile_syslog_line(log, r'FusionStor[\S]*:(\s\S*):')
            if level == 'INFO':
                continue
            errcode = self.__compile_syslog_line(log, r'FusionStor[\s\S]*:\s*(\d*)')
            process_id = self.__compile_syslog_line(log, r'FusionStor\[(\S+)\]:')
            time = self.__compile_syslog_line(log, r'\d{1,2}:\d{1,2}:\d{1,2}')


            values = {'detail':log, 'position':host.ip, 'host_id':host.id, 'level': level, 'returncode':errcode}
            alert_api.alert_create(values)

            is_send2ui = True

        if is_send2ui:
            self.send_message('reload_alert')

    def _get_syslog_path(self, host_ip):
        platform_cmd = '''python -c "import platform;print ','.join(platform.dist())"'''
        res = self.api_sync_call(host_ip, platform_cmd)

        distro = res.split(',')[0]
        syslogPath = '/var/log/messages'
        if distro.lower() == 'centos':
            syslogPath = '/var/log/messages'
        if distro.lower() == 'ubuntu':
            syslogPath = '/var/log/syslog'
        return syslogPath

    def __compile_syslog_line(self, log, rep):
        regexp = re.compile(rep)
        result = regexp.findall(log)
        result = ''.join(result).strip()
        return result

    def delete_older(self):
        now = datetime.datetime.now()
        LOG.info('delete_older alert')
        models.Alert.is_check_deleted = 1
        alerts = models.Alert.query.all()
        for alert in alerts: 
            delta = datetime.timedelta(days=config.alert_validity)
            if now - alert.created_at > delta:
                if not alert.deleted :
                    alert.delete()
                alert.hard_delete()


if __name__ == '__main__':
    monitorm = MonitorManager()
